package com.roberto.simulation;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.utils.Array;
import com.roberto.entities.Invader;
import com.roberto.entities.Player;
import com.roberto.entities.Shield;
import com.roberto.entities.Shot;
import com.roberto.entities.UFO;
import com.roberto.main.Main;

/**
 * The renderer receives a simulation and renders it.
 * 
 */
public class Renderer implements IRenderer {
    private static final String STATUS = "SCORE                                           LIVES";
    private static final String THE_END = "GAME OVER";

    /** sprite batch to draw text **/
    private SpriteBatch spriteBatch;
    /** the font **/
    private BitmapFont font;

    private OrthographicCamera camera;
    private ShapeRenderer theLine;
    private int gameOverLength = 0;
    private long gameOverTick;
    private final Sprite background = new Sprite(Main.backgroundTexture);

    public Renderer() {
        try {
            Main.pref.updateCFG();
            camera = new OrthographicCamera();
            camera.setToOrtho(false, Main.WIDTH, Main.HEIGHT);
            spriteBatch = new SpriteBatch();
            spriteBatch.maxSpritesInBatch = 120;

            theLine = new ShapeRenderer();
            font = new BitmapFont(Gdx.files.internal("res/fonts/arcade.fnt"), Gdx.files.internal("res/fonts/arcade.png"), false);

            background.setBounds(0, 0, Main.WIDTH, Main.HEIGHT);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        camera.update();
        spriteBatch.setProjectionMatrix(camera.combined);
        theLine.setProjectionMatrix(camera.combined);
    }

    public void render(GameLogic simulation, float delta) {
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        spriteBatch.begin();
        renderBackground();

        spriteBatch.enableBlending();
        simulation.player.getSprite().draw(spriteBatch);
        renderExplosions(simulation);
        renderInvaders(simulation.invaders);
        renderUfo(simulation.ufo);
        renderBlocks(simulation.shields);
        renderShots(simulation.bullets);
        renderGameOver(simulation.player);

        font.setScale(1);
        if (Main.pref.showFPS) {
            font.setColor(Color.YELLOW);
            font.draw(spriteBatch, Gdx.graphics.getFramesPerSecond() + "",
                    Main.WIDTH / 2f - font.getBounds(Gdx.graphics.getFramesPerSecond() + "").width / 2f, Main.HEIGHT - 22);
        }
        font.setColor(Color.WHITE);
        font.draw(spriteBatch, STATUS, GameLogic.MARGIN + 5, Main.HEIGHT - 22);
        font.setColor(Color.GREEN);
        font.draw(spriteBatch, simulation.score + "", GameLogic.MARGIN + 170, Main.HEIGHT - 22);

        for (int i = 0; i < simulation.player.lives; i++) {
            simulation.livesSprite[i].setPosition(800 + (60 * i), Main.HEIGHT - 45);
            simulation.livesSprite[i].draw(spriteBatch);
        }

        spriteBatch.end();
        // theLine.setProjectionMatrix(camera.combined);
        theLine.begin(ShapeType.FilledRectangle);
        theLine.setColor(Color.GREEN);
        theLine.filledRect(GameLogic.MARGIN, 30, Main.WIDTH - GameLogic.MARGIN * 2, 3);
        // rect.filledRect(MARGIN, 0, 3, Main.HEIGHT);
        // rect.filledRect(Main.WIDTH - MARGIN, 0, 3, Main.HEIGHT);

        theLine.end();
    }

    private void renderGameOver(Player player) {
        if (player.lives == 0) {
            font.setScale(3);
            font.setColor(Color.WHITE);
            font.draw(spriteBatch, THE_END.subSequence(0, gameOverLength), Main.WIDTH / 2 - font.getBounds(THE_END).width / 2, Main.HEIGHT
                    / 2 + font.getLineHeight());
            if (gameOverLength == THE_END.length()) {
                font.setScale(1);
                font.setColor(Color.WHITE);
                font.draw(spriteBatch, "PRESS ENTER TO SPACE MENU", Main.WIDTH / 2 - font.getBounds("PRESS SPACE TO ENTER MENU").width / 2,
                        Main.HEIGHT / 2);
            }
            if (Main.getCurrentTime() - gameOverTick >= 400) {
                gameOverLength = gameOverLength == THE_END.length() ? THE_END.length() : ++gameOverLength;
                gameOverTick = Main.getCurrentTime();
            }
        }
    }

    private void renderExplosions(GameLogic sim) {
        if (sim.invaderJustDied) {
            Invader.invExplosion.draw(spriteBatch);
            if (sim.randomUfoScore > 0) {
                font.setColor(Color.RED);
                font.setScale(2f);
                font.draw(spriteBatch, sim.randomUfoScore + "", Invader.invExplosion.getX(), Invader.invExplosion.getY());
            }
            if (Main.getCurrentTime() - sim.diedTick >= 350) {
                sim.invaderJustDied = false;
                sim.randomUfoScore = 0;
            }
        }

    }

    private void renderInvaders(Array<Invader> invaders) {
        for (Invader invader : invaders) {
            invader.getSprite().draw(spriteBatch);
        }
    }

    private void renderUfo(UFO ufo) {
        if (ufo.onGameField() && GameLogic.running) {
            ufo.getSprite().draw(spriteBatch);
        }

    }

    private void renderBlocks(Shield[] shields) {
        for (Shield shield : shields) {
            for (int i = 0; i < 10; i++) {
                shield.getSprite(i).draw(spriteBatch);
            }

        }

    }

    private void renderShots(Array<Shot> bullets) {
        for (Shot bullet : bullets) {
            bullet.getSprite().draw(spriteBatch);
        }
    }

    private void renderBackground() {
        spriteBatch.disableBlending();
        background.draw(spriteBatch);
    }

    public void dispose() {
        spriteBatch.dispose();
        font.dispose();
        theLine.dispose();
    }
}
